import UMe, { sers } from "../../frameSccript/system/OverallSystem ";
import timePlugIn, { timeFabric } from "../TimePlugIn";

/**
 *    ------------ ipha Class 一些类  ----------
 */

namespace iClass {
    /**
     * 一发类基础
    */
    abstract class Ipha_ClassBase {
        abstract _className: string;

        protected _Initialize() {
            console.log("---------", this._className, "------创建完毕");
        }

        protected clear() {
            console.log("---------", this._className, "------清除完毕");
        }
    }


    /**
    *  节点触摸抽象类
    */
    export abstract class ItemTouch extends cc.Component {

        protected enableTouchEventKey: string = "ipha-touch-item-enable-event-key";
        protected disableTouchEventKey: string = "ipha-touch-item-disable-event-key";

        protected isCanTouch: boolean;

        protected initPos: cc.Vec2;

        // onLoad() {
        //     this.Init();
        // }

        // Init() {
        //     this.onListenerEnableTouch();



        //     this.isCanTouch = false;
        //     this.scheduleOnce(() => {
        //         this.initPos = this.node.getPosition().clone();
        //         this.isCanTouch = true;
        //     });
        // }

        abstract OnTouchStart(e: cc.Event.EventTouch): void;
        abstract OnTouchMove(e: cc.Event.EventTouch): void;
        abstract OnTouchEnd(e: cc.Event.EventTouch): void;
        abstract OnTouchCancel(e: cc.Event.EventTouch): void;
        // OnTouchStart(e: cc.Event.EventTouch) {
        //     if (!this.isCanTouch) return;
        // }
        // OnTouchMove(e: cc.Event.EventTouch) {
        //     if (!this.isCanTouch) return;
        // }
        // OnTouchEnd(e?: cc.Event.EventTouch) {
        //     if (!this.isCanTouch) return;
        // }
        // OnTouchCancel(e: cc.Event.EventTouch) {
        //     if (!this.isCanTouch) return;
        //     this.OnTouchEnd();
        // }

        abstract onListenerEnableTouch(): void;
        // onListenerEnableTouch() {
        //     IphaOS.Canvas().on(this.enableTouchEventKey, this.enableTouch, this);
        //     IphaOS.Canvas().on(this.disableTouchEventKey, this.disableTouch, this);

        //     this.node.on("touchstart", this.OnTouchStart, this);
        //     this.node.on("touchmove", this.OnTouchMove, this);
        //     this.node.on("touchend", this.OnTouchEnd, this);
        //     this.node.on("touchcancel", this.OnTouchCancel, this);
        // }
        abstract offListenerEnableTouch(): void;
        // offListenerEnableTouch() {
        //     IphaOS.Canvas().off(this.enableTouchEventKey, this.enableTouch, this);
        //     IphaOS.Canvas().off(this.disableTouchEventKey, this.disableTouch, this);

        //     this.node.off("touchstart", this.OnTouchStart, this);
        //     this.node.off("touchmove", this.OnTouchMove, this);
        //     this.node.off("touchend", this.OnTouchEnd, this);
        //     this.node.off("touchcancel", this.OnTouchCancel, this);
        // }

        abstract enableTouch(): void;
        abstract disableTouch(): void;
        // enableTouch() {
        //     console.log("enableTouch this.isCanTouch :",this.isCanTouch);
        //     this.isCanTouch = true;
        // }

        // disableTouch() {
        //     console.log("disableTouch this.isCanTouch :",this.isCanTouch);
        //     this.isCanTouch = false;
        // }

        // onDestroy() {
        //     this.offListenerEnableTouch();
        // }


    }

    /**
     * 定时连点基础类
     */
    export class ClickCnt extends Ipha_ClassBase {
        _className: string = "Ipha_ClickCnt";
        /**
         * 点击计数
         * @param maxCount 最大点击次数
         * @param delay 间隔多长时间次数重置,单位：秒
         */
        constructor(maxCount?: number, delay?: number) {
            super();
            maxCount && (this.maxCount = maxCount);
            this.maxCount = this.maxCount < 0 ? 1 : this.maxCount;
            delay && (this.delay = delay);
            this.delay = this.delay < 0 ? 0 : this.delay;
            this._Initialize();
        }

        delay: number = 5;
        maxCount: number = 5;
        date: number = 0;
        count: number = 0;

        add(): boolean {
            let date = Date.now();

            if (date - this.date > this.delay * 1000) {
                this.count = 0;
            }

            this.count++;
            this.date = date;

            if (this.count >= this.maxCount) {
                this.count = 0;
                return true;
            } else {
                return false;
            }
        }

        clear() {
            this.count = 0;
            this.date = 0;
        }
    }

    /**
     * 单日解锁基础类
     */
    export class UnlockForDay extends Ipha_ClassBase {
        _className: string = "UnlockForTime";

        /**
         * 单日解锁基础类
         * @param localStorageKey 本地缓存key
         */
        constructor(localStorageKey: string) {
            super();
            this._localStorageKey = localStorageKey;

            let tF: timeFabric = timePlugIn().getNowTime();
            // let localStorage: LocalStorage = cc.sys.localStorage;
            // let time = localStorage.getItem(this._localStorageKey);
            let time = UMe.Servers.localStorageSrv.get(this._localStorageKey);
            if (time == null || time == "") {
                this._value = "";
            } else {
                this._value = JSON.parse(time);
            }
            this._Initialize();
        }

        private _localStorageKey: string = "";
        private _value: string = "";

        unlock() {
            let tF: timeFabric = timePlugIn().getNowTime();
            this._value = `${tF.year}-${tF.month}-${tF.date}`;
            UMe.Servers.localStorageSrv.set(this._localStorageKey, JSON.stringify(this._value));
            // let localStorage: LocalStorage = cc.sys.localStorage;
            // localStorage.setItem(this._localStorageKey, JSON.stringify(this._value));
        }

        isUnlock(): boolean {
            let tF: timeFabric = timePlugIn().getNowTime();
            if (this._value != `${tF.year}-${tF.month}-${tF.date}`) {
                return false;
            } else {
                return true;
            }
        }
    }

    /**
     * 一次永久解锁基础类
     */
    export class UnlockForever extends Ipha_ClassBase {
        _className: string = "UnlockForever";

        /**
         * 一次永久解锁基础类
         * @param localStorageKey 本地缓存key
         */
        constructor(localStorageKey: string) {
            super();
            this._localStorageKey = localStorageKey;

            // let localStorage: LocalStorage = cc.sys.localStorage;
            // let unlock = localStorage.getItem(this._localStorageKey);
            let unlock = UMe.Servers.localStorageSrv.get(this._localStorageKey);
            if (unlock == null || unlock == "") {
                this._value = 0;
            } else {
                this._value = JSON.parse(unlock);
            }
            this._Initialize();
        }

        private _localStorageKey: string = "";
        private _value: number = 0;

        unlock() {
            this._value = 1;
            // let localStorage: LocalStorage = cc.sys.localStorage;
            // localStorage.setItem(this._localStorageKey, JSON.stringify(this._value));
            UMe.Servers.localStorageSrv.set(this._localStorageKey, JSON.stringify(this._value));
        }

        isUnlock() {
            return this._value == 1;
        }
    }

    /**
     * 数组增强基础类
     */
    export class ArrayBoostBase<T> extends Ipha_ClassBase {

        _className: string = "ArrayBoostBase";

        /**
         * 数组增强基础类
         * @param name 名字
         */
        constructor(name?: string) {
            super();
            name && (this._className = name);
            this._Initialize();
        }

        protected _value: T[] = [];
        get data() {
            return this._value;
        }

        /** 随机乱序 */
        randomSort() {
            this._value.sort((a, b) => Math.random() - 0.5);
        }

        /** 初始化填充 */
        initFill(cnt: number, arg: T) {
            this._value = new Array(cnt).fill(arg);
        }

        clear() {
            this._value = [];
        }

        spilice(predicate: (value: T, index: number, obj: T[]) => unknown): boolean {
            let index = this._value.findIndex(predicate);
            if (index != -1) {
                this._value.splice(index, 1);
                return true;
            } else {
                console.error(`${this._className}中未找到需要删除的元素`);
                return false;
            }
        }
    }

    /**
     * 二维数组增强基础类
     */
    export class TwoDimensionalArrayBoostBase<T> extends Ipha_ClassBase {
        _className: string = "二维数组增强基础";

        /**
         * 二维数组增强基础类
         * @param height 数组高度，即第一层数组长度
         * @param width 数组宽度，即第二层数组长度
         * @param name 名字
         */
        constructor(height: number, width: number, name?: string) {
            super();

            this._className = name || this._className;

            this._size.height = height;
            this._size.width = width;

            this._Init(height, width);
            this._Initialize();
        }

        protected _value: T[][] = [];

        private _size = { height: 0, width: 0 };
        public get size() { return this._size; }

        private _count: number = 0;
        public get count() { return this._count; }

        private _Init(height: number, width: number) {
            for (let y = 0; y < height; y++) {
                this._value[y] = [];
                for (let x = 0; x < width; x++) {
                    this._value[y][x] = null;
                }
            }

            this._count = height * width;
        }

        get data() {
            return this._value;
        }

        clear(height?: number, width?: number) {
            height && (this._size.height = height);
            width && (this._size.width = width);
            this._value = [];
            this._Init(this._size.height, this._size.width);
        }

        forEachAll(callbackfn: (valueX: T, indexX: number, arrayX: T[], valueY?: T[], indexY?: number, arrayY?: T[][]) => void) {
            this._value.forEach((elemY, indexY, arrY) => {
                elemY.forEach((elemX, indexX, arrX) => {
                    callbackfn(elemX, indexX, this._value[indexY], elemY, indexY, this._value);
                });
            });
        }
    }

    /**
     * 节点池增强基础类
     */
    export class NodePoolBoostBase extends Ipha_ClassBase {
        _className: string = "NodePoolBoostBase";

        /**
         * 节点池增强基础类
         * @param prefab 使用的预制体
         * @param poolHandlerComp 处理节点回收和复用事件逻辑的组件类型或名称。
         */
        constructor(prefab: cc.Prefab, poolHandlerComp?: string | { prototype: cc.Component; }) {
            super();
            this._nodePool = new cc.NodePool(poolHandlerComp);
            this._prefab = prefab;
            this._Initialize();
        }

        protected _nodePool: cc.NodePool = null;

        protected _prefab: cc.Prefab = null;

        getPool() {
            return this._nodePool;
        }

        get() {
            if (this._nodePool.size() > 0) {
                return this._nodePool.get();
            } else {
                for (let i = 0; i < 5; i++) {
                    this._nodePool.put(cc.instantiate(this._prefab));
                }
                return this._nodePool.get();
            }
        }

        put(node: cc.Node) {
            this._nodePool.put(node);
        }

        clear() {
            this._nodePool.clear();
        }

        size() {
            return this._nodePool.size();
        }
    }

    /**
     * 节点委托基础类
     */
    export class NodeDelegateBase extends Ipha_ClassBase {
        _className: string = "NodeDelegateBase";

        /**
         * 节点委托基础类
         * @param node 需要委托的节点
         */
        constructor(node?: cc.Node) {
            super();
            node && (this._node = node);
            this._Initialize();
        }

        private _node: cc.Node = null;

        get node() {
            return this._node;
        }
        set node(node: cc.Node) {
            this._node = node;
        }

        remove() {
            this._node.destroy();
            this._node = null;
        }

        getHave() {
            return this._node && this._node.isValid;
        }
    }

    /**
     * 缓存数字类
     */
    export class LocalStorageNumber extends Ipha_ClassBase {
        _className: string = "缓存数字类";

        constructor(key: string, initNumber: number = 0, name?: string, min?: number, max?: number) {
            super();

            this._numberLocalStorageKey = key;
            this._initNumber = initNumber;
            name && (this._className = name);
            min && (this._min = min);
            max && (this._max = max);

            this._Initialize();
        }

        protected _numberLocalStorageKey: string = "";

        protected _initNumber: number = 0;

        protected _value: number = 0;

        protected _min: number = NaN;

        protected _max: number = NaN;

        protected _Initialize(): void {
            let nL = sers().localStorageSrv.get(this._numberLocalStorageKey);
            if (nL != null && nL != "") {
                this._value = JSON.parse(nL);
            } else {
                this.set(this._initNumber);
            }
            super._Initialize();
        }

        set(num: number) {
            this._value = num;
            if (!isNaN(this._min)) {
                this._value = this._value < this._min ? this._min : this._value;
            }
            if (!isNaN(this._max)) {
                this._value = this._value > this._max ? this._max : this._value;
            }
            sers().localStorageSrv.set(this._numberLocalStorageKey, JSON.stringify(this._value));
        }

        get() {
            return this._value;
        }

        add(num: number = 1) {
            this.set(this._value + num);
        }
    }

    /**
     * 物理碰撞回调
     */
    export abstract class PhysicsColliderCallBack {
        /** 只在两个碰撞体开始接触时被调用一次 */
        abstract onBeginContact: (contact: cc.PhysicsContact, selfCollider: cc.PhysicsCollider, otherCollider: cc.PhysicsCollider) => any;
        /** 只在两个碰撞体结束接触时被调用一次 */
        abstract onEndContact: (contact: cc.PhysicsContact, selfCollider: cc.PhysicsCollider, otherCollider: cc.PhysicsCollider) => any;
        /** 每次将要处理碰撞体接触逻辑时被调用 */
        abstract onPreSolve: (contact: cc.PhysicsContact, selfCollider: cc.PhysicsCollider, otherCollider: cc.PhysicsCollider) => any;
        /** 每次处理完碰撞体接触逻辑时被调用 */
        abstract onPostSolve: (contact: cc.PhysicsContact, selfCollider: cc.PhysicsCollider, otherCollider: cc.PhysicsCollider) => any;
    }
    /**
     * 碰撞回调
     */
    export abstract class ColliderCallBack {
        /**
        * 当碰撞产生的时候调用
        * @param other 产生碰撞的另一个碰撞组件
        * @param self  产生碰撞的自身的碰撞组件
        */
        abstract onCollisionEnter: (other: cc.Collider, self: cc.Collider) => any;
        /**
         * 当碰撞产生后，碰撞结束前的情况下，每次计算碰撞结果后调用
         * @param other 产生碰撞的另一个碰撞组件
         * @param self  产生碰撞的自身的碰撞组件
         */
        abstract onCollisionStay: (other: cc.Collider, self: cc.Collider) => any;
        /**
        * 当碰撞结束后调用
        * @param other 产生碰撞的另一个碰撞组件
        * @param self  产生碰撞的自身的碰撞组件
        */
        abstract onCollisionExit: (other: cc.Collider, self: cc.Collider) => any;
    }
}

export default iClass;